package com.java110.accessControl.adapter.dahuatech;

import com.alibaba.fastjson.JSONObject;
import com.dahuatech.hutool.http.Method;
import com.dahuatech.icc.brm.model.v202010.person.BrmPersonUploadImgRequest;
import com.dahuatech.icc.brm.model.v202010.person.BrmPersonUploadImgResponse;
import com.dahuatech.icc.exception.ClientException;
import com.dahuatech.icc.oauth.http.DefaultClient;
import com.dahuatech.icc.oauth.http.IClient;
import com.dahuatech.icc.oauth.model.v202010.GeneralRequest;
import com.dahuatech.icc.oauth.model.v202010.GeneralResponse;
import com.java110.accessControl.adapter.DefaultAbstractAccessControlAdapt;
import com.java110.core.adapt.ICallAccessControlService;
import com.java110.core.config.Java110Properties;
import com.java110.core.factory.MappingCacheFactory;
import com.java110.core.factory.MqttFactory;
import com.java110.core.factory.NotifyAccessControlFactory;
import com.java110.core.service.machine.IMachineService;
import com.java110.core.service.user.ICommunityPersonService;
import com.java110.core.thread.AddUpdateFace;
import com.java110.core.util.Assert;
import com.java110.core.util.SeqUtil;
import com.java110.core.util.StringUtil;
import com.java110.entity.accessControl.HeartbeatTaskDto;
import com.java110.entity.accessControl.UserFaceDto;
import com.java110.entity.cloud.MachineHeartbeatDto;
import com.java110.entity.machine.MachineDto;
import com.java110.entity.machine.MachineFaceDto;
import com.java110.entity.openDoor.OpenDoorDto;
import com.java110.entity.response.ResultDto;
import com.java110.entity.user.CommunityPersonDto;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.List;

/**
 * 大华平台门禁
 * 组织管理->设备管理->部门管理->人员管理->卡片管理->门禁授权
 * 组织管理：组织根节点001，设备是挂在组织节点下；跳过组织管理是可以的，设备添加选择根节点
 * 设备管理：设备增删改接口不支持，查询门禁设备通道，通道类型选择7
 * 部门管理:部门根节点是1，人员是挂在部门节点下；跳过部门管理是可以的，人员添加选择根节点
 * 人员管理：人员上传照片-》增、改录入人员信息，授权前查询人员
 * 卡片管理：人像刷门与刷卡开门都需要建卡，人像、指纹授权需绑定人员主卡
 * 门禁授权：授权方式有按人/卡，按门、按部门授权，调用接口也不一样
 * 备注：新增卡片与门禁授权需间隔一定时间，毫秒级，基础数据卡片信息同步门禁是通过mq，否则可能会报卡片不存在错误
 * <p>
 * <p>
 * 对接流程
 * step1:上传照片，参考API文档-基础资源-人员管理-人员图片上传
 * step2:新增人员，并设置图片路径，参考API文档-基础资源-人员管理-人员新增/人员批量新增
 * step3:新增卡片，参考API文档-基础资源-卡片管理-卡片新增/卡片批量开卡，间隔一定时间调step4接口，推荐5秒
 * step4:授权，参考API文档-门禁管理-门禁授权-新增按人授权/修改按人授权/新增按部门授权(通道)/新增按部门授权(门组)
 */
@Service("daHuaHttpAssessControlProcessAdapt")
public class DaHuaHttpAssessControlProcessAdapt extends DefaultAbstractAccessControlAdapt {

    private static Logger logger = LoggerFactory.getLogger(DaHuaHttpAssessControlProcessAdapt.class);
    //public static Function fun=new Function();

    private static final String DEFAULT_PORT = "8090"; //端口

    @Autowired
    private IMachineService machineServiceImpl;

    @Autowired
    private RestTemplate outRestTemplate;

    @Autowired
    private ICommunityPersonService communityPersonServiceImpl;

    public static final long START_TIME = new Date().getTime() - 1000 * 60 * 60;
    public static final long END_TIME = new Date().getTime() + 1000 * 60 * 60 * 24 * 365;

    public static final String OPEN_TYPE_FACE = "1000"; // 人脸开门

    //根据身份证号查询人员信息
    public static final String GET_BY_PAPER_NUMBER = "/evo-apigw/evo-brm/1.2.0/person/subsystem/get-by-paper-number";

    public static final String GENERATE_ID = "/evo-apigw/evo-brm/1.0.0/person/generate-id";

    public static final String PERSON_ADD = "/evo-apigw/evo-brm/1.2.0/person/subsystem/add";
    public static final String PERSON_DELETE = "/evo-apigw/evo-brm/1.0.0/person/delete";


    public static final String PERSON_UPLOAD_IMG = "/evo-apigw/evo-brm/1.2.0/person/upload/img";

    public static final String UPDATE_BIOSIGNATURE_FACE = "/evo-apigw/evo-brm/1.0.0/person/subsystem/update-biosignature-face";

    public static final String CARD_GENERATE_ID = "/evo-apigw/evo-brm/1.0.0/card/generate-id";


    public static final String CARD_ADD = "/evo-apigw/evo-brm/1.0.0/card/add";
    public static final String CARD_UPDATE = "/evo-apigw/evo-brm/1.0.0/card/update";
    public static final String CARD_DELETE = "/evo-apigw/evo-brm/1.0.0/card/delete";


    public static final String DOOR_AUTHORITY = "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/doorAuthority";
    public static final String OPEN_DOOR = "/evo-apigw/evo-accesscontrol/1.0.0/card/accessControl/channelControl/openDoor";


    public static final String GET_MACHINE = "/evo-apigw/evo-brm/1.0.0/device/";

    //图片后缀
    public static final String IMAGE_SUFFIX = ".jpg";

    @Override
    public void initAssessControlProcess() {
        logger.debug("初始化是配置器");


    }

    @Override
    public ResultDto initAssessControlProcess(MachineDto machineDto) {
        return new ResultDto(ResultDto.SUCCESS, ResultDto.SUCCESS_MSG);
    }

    @Override
    public String getFace(MachineDto machineDto, UserFaceDto userFaceDto) {
        String personId = "";
        try {
            //根据身份证查询
            personId = getPersonIdByIdCard(userFaceDto.getIdNumber());
            if (personId == null) return AddUpdateFace.MACHINE_HAS_NOT_FACE;

            if (StringUtil.isEmpty(personId)) {
                return AddUpdateFace.MACHINE_HAS_NOT_FACE;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return personId;
    }

    private static String getPersonIdByIdCard(String idNumber) throws ClientException {
        IClient iClient = new DefaultClient();

        /**
         * 1、请求地址是统一网关入口，以 /evo-apigw 开头
         * 2、方法参见 @see com.dahuatech.hutool.http.Method
         */
        GeneralRequest generalRequest = new GeneralRequest(GET_BY_PAPER_NUMBER + "?paperNumber=" + idNumber, Method.GET);
        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
        JSONObject outParam = JSONObject.parseObject(generalResponse.getResult());

        if (!outParam.containsKey("data")) {
            return null;
        }

        JSONObject data = outParam.getJSONObject("data");
        return data.getString("id");
    }

    @Override
    public ResultDto addFace(MachineDto machineDto, UserFaceDto userFaceDto) {
        String id = "";
        try {
            IClient iClient = new DefaultClient();

            //上传头像
            BrmPersonUploadImgRequest brmPersonUploadImgRequest = new BrmPersonUploadImgRequest(Java110Properties.getCloudFacePath() + userFaceDto.getFacePath());
            BrmPersonUploadImgResponse brmPersonUploadImgResponse = iClient.doAction(brmPersonUploadImgRequest, brmPersonUploadImgRequest.getResponseClass());
            if (!brmPersonUploadImgResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, brmPersonUploadImgResponse.getErrMsg());
            }
            String path = brmPersonUploadImgResponse.getData().getFileUrl();

            /**
             * 1、请求地址是统一网关入口，以 /evo-apigw 开头
             * 2、方法参见 @see com.dahuatech.hutool.http.Method
             */
            GeneralRequest generalRequest = new GeneralRequest(GENERATE_ID, Method.GET);
            GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            JSONObject outParam = JSONObject.parseObject(generalResponse.getResult());
            if (!outParam.containsKey("data")) {
                return new ResultDto(ResultDto.ERROR, "人员全局id生成失败");
            }
            JSONObject data = outParam.getJSONObject("data");
            id = data.getString("id");

            JSONObject paramIn = new JSONObject();
            paramIn.put("id", id);
            paramIn.put("name", userFaceDto.getName());
            paramIn.put("code", userFaceDto.getUserId());
            paramIn.put("paperType", 111);
            paramIn.put("paperNumber", userFaceDto.getIdNumber());
            paramIn.put("paperAddress", "青海省西宁市");
            paramIn.put("departmentId", 1);
            generalRequest = new GeneralRequest(PERSON_ADD, Method.POST);
            generalRequest.body(paramIn.toJSONString());
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }
            // 头像和人员关联
            paramIn = JSONObject.parseObject("{\n" +
                    "  \"personBiosignatures\": []\n" +
                    "}");
            JSONObject personBiosignature = new JSONObject();
            personBiosignature.put("personId", id);
            personBiosignature.put("type", 3);
            personBiosignature.put("index", 1);
            personBiosignature.put("path", path);
            paramIn.getJSONArray("personBiosignatures").add(personBiosignature);
            generalRequest = new GeneralRequest(UPDATE_BIOSIGNATURE_FACE, Method.PUT);
            generalRequest.body(paramIn.toJSONString());
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

            //卡片ID
            generalRequest = new GeneralRequest(CARD_GENERATE_ID, Method.GET);
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            outParam = JSONObject.parseObject(generalResponse.getResult());
            if (!outParam.containsKey("data")) {
                return new ResultDto(ResultDto.ERROR, "人员全局id生成失败");
            }
            data = outParam.getJSONObject("data");
            String cardId = data.getString("id");

            paramIn = new JSONObject();
            paramIn.put("id", cardId);
            paramIn.put("cardNumber", userFaceDto.getLink());
            paramIn.put("category", "0");
            paramIn.put("cardType", "0");
            paramIn.put("departmentId", 1);
            paramIn.put("startDate", userFaceDto.getStartTime());
            paramIn.put("endDate", userFaceDto.getEndTime());
            generalRequest = new GeneralRequest(CARD_ADD, Method.POST);
            generalRequest.body(paramIn.toJSONString());
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

            //查询设备
            generalRequest = new GeneralRequest(GET_MACHINE + machineDto.getMachineCode(), Method.GET);
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            outParam = JSONObject.parseObject(generalResponse.getResult());
            if (!outParam.containsKey("data")) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }
            JSONObject channel = outParam.getJSONObject("data").getJSONArray("units").getJSONObject(0).getJSONArray("channels").getJSONObject(0);


            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

            new Thread(new Runnable() {
                @Override
                public void run() {
                    //卡片和 设备通道关联
                    try {
                        Thread.sleep(5000);
                        JSONObject paramIn = JSONObject.parseObject("{\n" +
                                "  \"cardPrivilegeDetails\": []\n" +
                                "}");
                        paramIn.put("cardNumbers", new String[]{userFaceDto.getLink()});
                        paramIn.put("timeQuantumId", "1");
                        JSONObject cardPrivilegeDetail = new JSONObject();
                        personBiosignature.put("privilegeType", 1);
                        personBiosignature.put("resouceCode", channel.getString("channelCode"));
                        paramIn.getJSONArray("cardPrivilegeDetails").add(cardPrivilegeDetail);
                        GeneralRequest generalRequest = new GeneralRequest(DOOR_AUTHORITY, Method.POST);
                        generalRequest.body(paramIn.toJSONString());
                        GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
                        logger.debug("返回信息，{}", generalResponse.getResult());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDto(ResultDto.ERROR, e.getLocalizedMessage());
        }
        return new ResultDto(ResultDto.SUCCESS, "操作成功");
    }

    @Override
    public ResultDto updateFace(MachineDto machineDto, UserFaceDto userFaceDto) {

        try {
            IClient iClient = new DefaultClient();

            //上传头像
            BrmPersonUploadImgRequest brmPersonUploadImgRequest = new BrmPersonUploadImgRequest(Java110Properties.getCloudFacePath() + userFaceDto.getFacePath());
            BrmPersonUploadImgResponse brmPersonUploadImgResponse = iClient.doAction(brmPersonUploadImgRequest, brmPersonUploadImgRequest.getResponseClass());
            if (!brmPersonUploadImgResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, brmPersonUploadImgResponse.getErrMsg());
            }
            String path = brmPersonUploadImgResponse.getData().getFileUrl();

            String personId = getPersonIdByIdCard(userFaceDto.getIdNumber());

            // 头像和人员关联
            JSONObject paramIn = JSONObject.parseObject("{\n" +
                    "  \"personBiosignatures\": []\n" +
                    "}");
            JSONObject personBiosignature = new JSONObject();
            personBiosignature.put("personId", personId);
            personBiosignature.put("type", 3);
            personBiosignature.put("index", 1);
            personBiosignature.put("path", path);
            paramIn.getJSONArray("personBiosignatures").add(personBiosignature);
            GeneralRequest generalRequest = new GeneralRequest(UPDATE_BIOSIGNATURE_FACE, Method.PUT);
            generalRequest.body(paramIn.toJSONString());
            GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

            //更新卡片有效期

            paramIn = new JSONObject();
            paramIn.put("cardNumber", userFaceDto.getLink());
            paramIn.put("isCoercion", "0");
            paramIn.put("startDate", userFaceDto.getStartTime());
            paramIn.put("endDate", userFaceDto.getEndTime());
            generalRequest = new GeneralRequest(CARD_UPDATE, Method.POST);
            generalRequest.body(paramIn.toJSONString());
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDto(ResultDto.ERROR, e.getLocalizedMessage());

        }
        return new ResultDto(ResultDto.SUCCESS, "操作成功");
    }

    @Override
    public ResultDto deleteFace(MachineDto machineDto, HeartbeatTaskDto heartbeatTaskDto) {

        try {
            IClient iClient = new DefaultClient();

            CommunityPersonDto communityPersonDto = new CommunityPersonDto();
            communityPersonDto.setExtPersonId(heartbeatTaskDto.getTaskid());
            communityPersonDto.setCommunityId(machineDto.getCommunityId());
            List<CommunityPersonDto> communityPersonDtos = communityPersonServiceImpl.queryCommunityPerson(communityPersonDto);

            Assert.listOnlyOne(communityPersonDtos, "人员不存在");


            String personId = getPersonIdByIdCard(communityPersonDtos.get(0).getIdNumber());

            // 头像和人员关联
            JSONObject paramIn = new JSONObject();
            paramIn.put("ids", new String[]{personId});
            GeneralRequest generalRequest = new GeneralRequest(PERSON_DELETE, Method.POST);
            generalRequest.body(paramIn.toJSONString());
            GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

            // 头像和人员关联
            paramIn = new JSONObject();
            paramIn.put("cardNumbers", new String[]{communityPersonDtos.get(0).getTel()});
            generalRequest = new GeneralRequest(CARD_DELETE, Method.POST);
            generalRequest.body(paramIn.toJSONString());
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {
                return new ResultDto(ResultDto.ERROR, generalResponse.getErrMsg());
            }

        } catch (Exception e) {
            e.printStackTrace();
            return new ResultDto(ResultDto.ERROR, e.getLocalizedMessage());

        }
        return new ResultDto(ResultDto.SUCCESS, "操作成功");
    }

    @Override
    public ResultDto clearFace(MachineDto machineDto, HeartbeatTaskDto heartbeatTaskDto) {

        return null;
    }


    /**
     * 扫描设备
     *
     * @return
     */
    @Override
    public List<MachineDto> scanMachine() throws Exception {


        return null;
    }


    @Override
    public void restartMachine(MachineDto machineDto) {


    }

    @Override
    public void openDoor(MachineDto machineDto) {
        try {
            IClient iClient = new DefaultClient();

            //查询设备
            GeneralRequest generalRequest = new GeneralRequest(GET_MACHINE + machineDto.getMachineCode(), Method.GET);
            GeneralResponse generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            JSONObject outParam = JSONObject.parseObject(generalResponse.getResult());

            JSONObject channel = outParam.getJSONObject("data").getJSONArray("units").getJSONObject(0).getJSONArray("channels").getJSONObject(0);

           JSONObject paramIn = new JSONObject();
            paramIn.put("channelCodeList", new String[]{channel.getString("channelCode")});
            generalRequest = new GeneralRequest(OPEN_DOOR, Method.POST);
            generalRequest.body(paramIn.toJSONString());
            generalResponse = iClient.doAction(generalRequest, generalRequest.getResponseClass());
            if (!generalResponse.isSuccess()) {

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public String httpFaceResult(MachineDto machineDto, String data) {
        ICallAccessControlService notifyAccessControlService = NotifyAccessControlFactory.getCallAccessControlService();
        JSONObject resultParam = new JSONObject();
        try {
            JSONObject body = JSONObject.parseObject(data);


            String userId = body.containsKey("personId") ? body.getString("personId") : "";
            String userName = "";
            if (!StringUtils.isEmpty(userId)) {
                MachineFaceDto machineFaceDto = new MachineFaceDto();
                machineFaceDto.setUserId(userId);
                machineFaceDto.setMachineId(machineDto.getMachineId());
                List<MachineFaceDto> machineFaceDtos = notifyAccessControlService.queryMachineFaces(machineFaceDto);
                if (machineFaceDtos != null && machineFaceDtos.size() > 0) {
                    userName = machineFaceDtos.get(0).getName();
                }

            }


            OpenDoorDto openDoorDto = new OpenDoorDto();
            openDoorDto.setFace(body.getString("base64"));
            openDoorDto.setUserName(userName);
            openDoorDto.setHat("3");
            openDoorDto.setMachineCode(machineDto.getMachineCode());
            openDoorDto.setUserId(userId);
            openDoorDto.setOpenId(SeqUtil.getId());
            openDoorDto.setOpenTypeCd(OPEN_TYPE_FACE);
            openDoorDto.setSimilarity(body.containsKey("identifyType") && "1".equals(body.getString("identifyType")) ? "100" : "0");


            freshOwnerFee(openDoorDto);

            notifyAccessControlService.saveFaceResult(openDoorDto);

        } catch (Exception e) {
            logger.error("推送人脸失败", e);
        }
        resultParam.put("result", 1);
        resultParam.put("success", true);
        return resultParam.toJSONString();//未找到设备

    }

    @Override
    public String heartbeat(String data, String machineCode) throws Exception {
        JSONObject info = JSONObject.parseObject(data);

        //设备ID
        //String machineCode = info.getString("deviceKey");
        String heartBeatTime = null;
        heartBeatTime = info.getString("time");
        MachineHeartbeatDto machineHeartbeatDto = new MachineHeartbeatDto(machineCode, heartBeatTime);
        ICallAccessControlService notifyAccessControlService = NotifyAccessControlFactory.getCallAccessControlService();
        notifyAccessControlService.machineHeartbeat(machineHeartbeatDto);
        JSONObject resultParam = new JSONObject();
        resultParam.put("result", 1);
        resultParam.put("success", true);
        return resultParam.toJSONString();//未找到设备
    }


    /**
     * 重启
     */
    public void setUiTitle(MachineDto machineDto) {


    }

}
